package com.daJiao.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.daJiao.domain.PageParam;
import com.daJiao.constants.Constants;
import com.daJiao.domain.SecurityUserDetails;
import com.daJiao.entity.SysMenu;
import com.daJiao.entity.SysRoleMenu;
import com.daJiao.entity.SysUserRole;
import com.daJiao.enums.DeleteFlagEnums;
import com.daJiao.exception.BusinessException;
import com.daJiao.mapper.SysMenuMapper;
import com.daJiao.service.SysMenuService;
import com.daJiao.service.SysRoleMenuService;
import com.daJiao.service.SysUserRoleService;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Resource
    private SysRoleMenuService sysRoleMenuService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Override
    public int saveMenu(SysMenu menu, SecurityUserDetails securityUser) {
        // 查询父节点信息
        SysMenu parentMenu = sysMenuMapper.selectById(menu.getPid());
        if(Objects.isNull(parentMenu)){
            throw new BusinessException("无效的父节点参数");
        }
        // 如果新增的是按钮级别的权限，父节点必须是菜单
        if(Constants.ACTION_TYPE.equals(menu.getType()) && Constants.ACTION_TYPE.equals(parentMenu.getType())){
            throw new BusinessException("父节点的类型必须是菜单");
        }
        menu.setLevel(Constants.ACTION_TYPE.equals(menu.getType()) ? Constants.YES : Constants.NO);
        menu.setLevel(parentMenu.getLevel() + 1);
        menu.setMenuCode(PinyinUtil.getPinyin(menu.getMenuName()));
        return sysMenuMapper.insert(menu);
    }

    @Override
    public int updateMenuInfo(SysMenu menu) {
        SysMenu sysMenu = sysMenuMapper.selectById(menu.getId());
        if(Objects.isNull(sysMenu)){
            throw new BusinessException("不合法的id");
        }
        menu.setMenuCode(PinyinUtil.getPinyin(menu.getMenuName()));
        menu.setUpdateTime(LocalDateTime.now());
        return sysMenuMapper.updateById(menu);
    }

    @Override
    public int delete(Long id, SecurityUserDetails securityUser) {
        SysMenu sysMenu = sysMenuMapper.selectById(id);
        if(Objects.isNull(sysMenu)){
            throw new BusinessException("不合法的id");
        }
        sysMenu.setUpdater(securityUser.getRealName());
        sysMenu.setUpdateBy(securityUser.getUserId());
        sysMenu.setDelFlag(DeleteFlagEnums.DELETE.getStatus());
        sysMenu.setUpdateTime(LocalDateTime.now());
        return sysMenuMapper.updateById(sysMenu);
    }

    @Override
    public Page<SysMenu> listPage(PageParam<SysMenu> pageParam) {
        return null;
    }

    @Override
    public List<Tree<Long>> getMenuTree(Long menuId) {
        List<SysMenu> menuList = sysMenuMapper.selectAllMenu();
        List<Tree<Long>> treeNodes = buildMenuTree(menuId, menuList);
        return treeNodes;
    }

    /**
     *
     * @param menuId
     * @param menuList
     * @return
     */
    private List<Tree<Long>> buildMenuTree(Long menuId, List<SysMenu> menuList) {
        Map<Long, String> menuMap = menuList.stream().collect(Collectors.toMap(SysMenu::getId, SysMenu::getMenuName));
        List<TreeNode<Long>> nodeList = CollUtil.newArrayList();
        for (SysMenu menu : menuList) {
            TreeNode node = new TreeNode(menu.getId(), menu.getPid(), menu.getMenuName(), menu.getNumber());
            String parentMenuName = menuMap.getOrDefault(menu.getPid(), "根菜单");
            Map<String, Object> map = Maps.newHashMap();
            map.put("parentName", parentMenuName);
            map.put("status", menu.getStatus());
            map.put("level", menu.getLevel());
            map.put("leaf", menu.getLeaf());
            map.put("icon", menu.getIcon());
            map.put("type", menu.getType());
            node.setExtra(map);
            nodeList.add(node);
        }

        // 配置
        TreeNodeConfig config = new TreeNodeConfig();
        config.setWeightKey("sort");
        config.setDeep(3);

        // 转换器
        List<Tree<Long>> treeNodes = TreeUtil.build(nodeList, menuId, config,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setWeight(treeNode.getWeight());
                    tree.setName(treeNode.getName());
                    tree.putExtra("level", treeNode.getExtra().get("level"));
                    tree.putExtra("parentName", treeNode.getExtra().get("parentName"));
                    tree.putExtra("status", treeNode.getExtra().get("status"));
                    tree.putExtra("level", treeNode.getExtra().get("level"));
                    tree.putExtra("leaf", treeNode.getExtra().get("leaf"));
                    tree.putExtra("type", treeNode.getExtra().get("type"));
                    tree.putExtra("icon", treeNode.getExtra().get("icon"));
                });
        return treeNodes;
    }

    @Override
    public List<SysMenu> getOwnMenus(Long userId) {
        // 查询这个用户又哪儿些角色
        List<SysUserRole> sysUserRoles = sysUserRoleService.list(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, userId));
        if(CollectionUtils.isEmpty(sysUserRoles)){
            throw new BusinessException("请联系管理员绑定角色");
        }

        List<String> roleIds = sysUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        // 查询角色所绑定的权限信息
        List<SysRoleMenu> roleMenus = sysRoleMenuService.getMenuByRoleIds(roleIds);
        if(CollectionUtils.isEmpty(roleMenus)){
            throw new BusinessException("请联系管理员给角色绑定对应菜单信息");
        }

        List<SysMenu> menus = sysMenuMapper.selectBatchIds(roleMenus.stream().map(SysRoleMenu::getMenuId).distinct().collect(Collectors.toList()));
        return menus.stream().filter(f -> Constants.MENU_TYPE.equals(f.getType())).collect(Collectors.toList());
    }

    @Override
    public List<Tree<Long>> getOwnTree(Long userId) {
        // 查询这个用户又哪儿些角色
        List<SysUserRole> sysUserRoles = sysUserRoleService.list(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, userId));
        if(CollectionUtils.isEmpty(sysUserRoles)){
            throw new BusinessException("请联系管理员绑定角色");
        }

        List<String> roleIds = sysUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        // 查询角色所绑定的权限信息
        List<SysRoleMenu> roleMenus = sysRoleMenuService.getMenuByRoleIds(roleIds);
        if(CollectionUtils.isEmpty(roleMenus)){
            throw new BusinessException("请联系管理员给角色绑定对应菜单信息");
        }

        List<SysMenu> menuList = sysMenuMapper.selectBatchIds(roleMenus.stream().map(SysRoleMenu::getMenuId).distinct().collect(Collectors.toList()));
        return buildMenuTree(Constants.Menu.ROOT, menuList);
    }
}
